Skip to content

feat(spa): audit fixes (widget kinds, iframe sandbox, checks, parity, i18n, perf) + dep ^1.6.0 + 1.11.0#675

Merged
MartinCastroAlvarez merged 6 commits into
mainfrom
feat/audit-fixes-1.11.0
Jun 2, 2026
Merged

feat(spa): audit fixes (widget kinds, iframe sandbox, checks, parity, i18n, perf) + dep ^1.6.0 + 1.11.0#675
MartinCastroAlvarez merged 6 commits into
mainfrom
feat/audit-fixes-1.11.0

Conversation

@MartinCastroAlvarez
Copy link
Copy Markdown
Owner

Implements the v1.9.0 security + UX/architecture audit findings (#664#670) and raises the django-admin-rest-api floor to ^1.6.0. Version bumped 1.10.1 → 1.11.0.

Per-issue summary

Decisions / caveats

  • Rich-rendered kinds: hidden, split-datetime, select-date, checkbox-multiple, select-multiple, autocomplete, autocomplete-multiple, file (limited), plus pre-existing password/radio/raw-id/shuttle/custom.
  • Tracked-fallback: any kind with no faithful renderer → unsupported_widget (visible note). autocomplete-multiple for a large M2M with no inlined choices degrades to the existing read-only M2M path.
  • select-date renders a single <input type=date> (same ISO value as Django's 3 selects, no semantics lost) rather than rebuilding three coupled selects.
  • Added django_admin_rest_api to the test project's INSTALLED_APPS (matches its design; the [enhancement] Add django.core.checks for startup misconfiguration with actionable hints #667 check expects it).

Verification (all green)

  • Python: ruff check ✅, ruff format --check ✅, mypy django_admin_react ✅ (no issues, 9 files), bandit ✅ (0 findings), pytest75 passed.
  • Frontend: pnpm typecheck ✅, pnpm lint:js ✅, pnpm lint:css ✅, pnpm test248 passed (35 files), pnpm build ✅ (LoginPage/CreatePage split into separate chunks).
  • pre-commit run --all-files ✅ on in-scope files.

Closes #664 #665 #666 #667 #668 #669 #670

🤖 Generated with Claude Code

martin-castro-laminr-ai and others added 6 commits June 2, 2026 03:13
Raise the REST API floor to 1.6.0 (form-spec now emits prepopulated_fields +
autocomplete hints consumed by the widget-kind rendering), bump the package
to 1.11.0, and add the [1.11.0] CHANGELOG section covering #664#670.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…8n (#664, #669)

#664: adaptFormSpec now maps all 23 WidgetKind values onto an exhaustive
Record<WidgetKind, WidgetHint|undefined> (a new kind is a compile error).
FieldInput renders hidden as a real hidden input, split-datetime as date+time,
select-date as a date input, checkbox-multiple/select-multiple as a checkbox
bank / <select multiple>, autocomplete(-multiple), and file (limited control +
legacy-admin note, upload tracked by #241). Kinds with no faithful control map
to an explicit operator-visible unsupported_widget tracked fallback — never a
silent wrong control. The test asserts every enum member maps sensibly.

#669: FieldInput's Lookup ↗ / lookup aria-label, — select — / (none), and the
time/array/range/FK placeholders now go through t(); new keys added to the
es/fr/pt catalogs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
legacy_url from the form-spec legacy-iframe fallback is now validated before
reaching the <iframe src> / <a href> sinks: only a same-origin http(s) URL is
framed/linked (new safeLegacyUrl helper, mirroring action-redirect.ts); a
javascript:/data:/blob: scheme or off-origin target renders an inert error
card. The iframe carries sandbox="allow-forms allow-scripts allow-same-origin".
SECURITY.md §QSEC-03 adds frame-src 'self' and documents the X-Frame-Options ↔
legacy-iframe interaction. Tests cover the validator and the rejection paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The changelist wire emits list_display_links; the Table/RecordCardList
primitives now link exactly the columns flagged isLink (set by ListPage from
the wire) instead of hard-pinning the first column — and link none / make the
row inert when the admin sets list_display_links = None. A pre-1.6.0 backend
(field absent) keeps the legacy first-column behaviour. Table tests cover the
explicit-link, no-link, and legacy-fallback paths.

Note: ListPage also gains virtualizeRows on the Table for #670 (committed next).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New django_admin_react/checks.py registers a manage.py check validator with
actionable hints: django_admin_rest_api missing from INSTALLED_APPS (Error),
unimportable ADMIN_SITE dotted path (Error), unknown DJANGO_ADMIN_REACT keys
(Error, at startup vs a lazy ValueError), API_URL_PREFIX requiring the consumer
to mount the API (Warning), and a missing built bundle/Vite manifest (Warning).
Registered in AppConfig.ready(). Adds django_admin_rest_api to the test
project's INSTALLED_APPS (per its design) and a full-coverage test_checks.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… parity fixes (#670, #668)

#670: LoginPage and CreatePage are now React.lazy-loaded at the route boundary
(out of the first-paint main chunk), wrapped in Suspense; App.tsx's "Page not
found." now goes through t(). The "Show all N" (?all) list path uses native
content-visibility row windowing (Table.virtualizeRows, wired in ListPage).

#668: README parity table corrected — raw_id_fields / radio_fields /
filter_horizontal flip to ✅ (they ship today), stale "does NOT carry through"
entries removed, and a new section documents empty_value_display (hard-coded —),
custom each_context, and list_select_related.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[parity] Form-spec renders only 5 of 23 widget.kind values (hidden, multi-selects, file, split-datetime silently wrong)

2 participants